package com.ttg.common.utils.sm;

import com.ttg.common.utils.StringUtil;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.KeyException;
import java.util.Arrays;


/**
 * @ClassName GmUtils
 * @Description 国密加密工具类 用作接口稳定，对外暴露
 * @Author sss
 * @Date 2022/6/8
 * @Version 1.0
 **/
public class GmUtils {
    /**
     * sm3 + byte2hex
     *
     * @param data 需要生成摘要的字符串
     * @return
     */
    public static String sm3(String data) {
        // data = new BASE64Encoder().encode(CryptoUtil.hex2bin(data));
        SM3Digest digest = new SM3Digest();
        digest.update(data.getBytes(), 0, data.getBytes().length);
        byte[] hash = new byte[digest.getDigestSize()];
        digest.doFinal(hash, 0);
        return CryptoUtil.bin2hex(hash).toLowerCase();

    }

    /**
     * sm3
     *
     * @param data 需
     * @return
     */
    public static byte[] sm3(byte[] data) {
        // data = new BASE64Encoder().encode(CryptoUtil.hex2bin(data));
        SM3Digest digest = new SM3Digest();
        digest.update(data, 0, data.length);
        byte[] hash = new byte[digest.getDigestSize()];
        digest.doFinal(hash, 0);
        return hash;

    }

    /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓SM4 ECB↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/

    /**
     * SM4 ECB 解密方案 + hex2byte
     *
     * @param descyptStr 待解密字符串（hex格式）
     * @param key        密钥 （32位hex格式密钥）
     * @return
     */
    public static String sm4ECBDecrypt(String descyptStr, String key) {
        return SM4Utils.decryptDataECB(descyptStr, key);
    }
    private static final String db="30326262663532633535653434653738";

    public static String sm4ECBDecrypt(String descyptStr) {
        return sm4ECBDecrypt(descyptStr,db);
    }
    /**
     * SM4 ECB 解密
     *
     * @param descyptBytes 密文字节数组
     * @param keyBytes     密钥字节数组
     * @param padding      是否补长
     * @return
     */
    public static byte[] sm4ECBDecrypt(byte[] descyptBytes, byte[] keyBytes, boolean padding) {
        return SM4Utils.decryptDataECB(descyptBytes, keyBytes, padding);
    }

    /**
     * SM4 ECB 加密方案 byte2hex
     *
     * @param encryptStr 密文字符串
     * @param key        密钥 （hex格式密钥）
     * @return 密文 （hex格式）
     */
    public static String sm4ECBEncrypt(String encryptStr, String key) {
        return SM4Utils.encryptDataECB(encryptStr, key);
    }

    /**
     * SM4 ECB 加密方案
     *
     * @param encryptBytes 密文字节数组
     * @param keyBytes     密钥字节数组
     * @param padding      是否补长
     * @return
     */
    public static byte[] sm4ECBEncrypt(byte[] encryptBytes, byte[] keyBytes, boolean padding) {
        return SM4Utils.encryptDataECB(encryptBytes, keyBytes, padding);
    }

    /*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑SM4 ECB↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/

    /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓SM4 CBC↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/

    /**
     * SM4 CBC 解密方案
     *
     * @param descyptStr 密文
     * @param key        密钥 （32位hex格式密钥）
     * @param iv         偏移量(hex格式)
     * @return
     */
    public static String sm4CBCDecrypt(String descyptStr, String key, String iv) {
        return SM4Utils.decryptDataCBC(descyptStr, key, iv);
    }

    /**
     * SM4 CBC 解密方案 自定义
     *
     * @param descyptBytes 密文字节数组
     * @param keyBytes     密钥字节数组
     * @param ivBytes      偏移量字节数组
     * @param padding      是否补长
     * @return
     */
    public static byte[] sm4CBCDecrypt(byte[] descyptBytes, byte[] keyBytes, byte[] ivBytes, boolean padding) {
        return SM4Utils.decryptDataCBC(descyptBytes, keyBytes, ivBytes, padding);
    }

    /**
     * SM4 ECB 加密方案 byte2hex
     *
     * @param encryptStr 密文字符串
     * @param key        密钥 （hex格式密钥）
     * @param iv         偏移量(hex格式)
     * @return 密文 （hex格式）
     */
    public static String sm4CBCEncrypt(String encryptStr, String key, String iv) {
        return SM4Utils.encryptDataCBC(encryptStr, key, iv);
    }

    /**
     * SM4 ECB 加密方案
     *
     * @param encryptBytes 密文字节数组
     * @param keyBytes     密钥字节数组
     * @param ivBytes      偏移量字节数组
     * @param padding      是否补长
     * @return
     */
    public static byte[] sm4CBCEncrypt(byte[] encryptBytes, byte[] keyBytes, byte[] ivBytes, boolean padding) {
        return SM4Utils.encryptDataCBC(encryptBytes, keyBytes, ivBytes, padding);
    }


    /*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑SM4 CBC↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/

    /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓SM2↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/

    /**
     * SM2 私钥解密
     *
     * @param descyptStr    密文
     * @param privateKeyStr 私钥 hex串
     * @return 明文字符串
     */
    public static String sm2DecryptByPrivateKey(String descyptStr, String privateKeyStr) {
        // 使用BC库加解密时密文以04开头，传入的密文前面没有04则补上
        byte[] dataByte = CryptoUtil.hex2bin(descyptStr);
        byte[] resultByte = sm2DecryptByPrivateKey(dataByte, privateKeyStr);
        return new String(resultByte, StandardCharsets.UTF_8);
    }

    /**
     * SM2 私钥解密
     *
     * @param descyptBytes  密文字节数组
     * @param privateKeyStr 私钥 hex串
     * @return 明文字节数组
     */
    public static byte[] sm2DecryptByPrivateKey(byte[] descyptBytes, String privateKeyStr) {
        return SMUtil.sm2DecryptDataForPriKey(descyptBytes, privateKeyStr);
    }

    /**
     * SM2 公钥加密
     *
     * @param encryptStr   明文
     * @param publicKeyStr 公钥 非压缩公钥 hex串
     * @return 密文 hex串
     * @throws KeyException key长度不正确
     */
    public static String sm2EncryptByPublicKey(String encryptStr, String publicKeyStr) throws KeyException {
        publicKeyStr = sm2PublicKey130to128(publicKeyStr);
        byte[] bytes = sm2EncryptByPublicKey(encryptStr.getBytes(StandardCharsets.UTF_8), publicKeyStr);
        return CryptoUtil.bin2hex(bytes);
    }

    /**
     * SM2 公钥加密
     *
     * @param encryptBytes 明文字节数组
     * @param publicKeyStr 公钥 非压缩公钥 hex串
     * @return 密文 字节数组
     * @throws KeyException key长度不正确
     */
    public static byte[] sm2EncryptByPublicKey(byte[] encryptBytes, String publicKeyStr) throws KeyException {
        publicKeyStr = sm2PublicKey130to128(publicKeyStr);
        return SMUtil.sm2EncryptDataForPubKey(encryptBytes, publicKeyStr);
    }

    /**
     * 微信交易使用
     * 将一个大整数转成一个指定长度的字节数组（前补零）
     *
     * @param bi 待转换的大整数
     * @return 转换后得到的字节数组
     */
    public static byte[] BigIntegerToByteArray(BigInteger bi) {
        int _byteLen = SM2Factory.getInstance().getPointByteLength();
        byte[] bibyte = bi.toByteArray();
        byte[] ubibyte;
        if (bibyte[0] == 0 && bibyte.length > _byteLen) {
            ubibyte = new byte[bibyte.length - 1];
            System.arraycopy(bibyte, 1, ubibyte, 0, ubibyte.length);
        } else {
            ubibyte = bibyte;
        }
        if (ubibyte.length >= _byteLen) {
            return ubibyte;
        } else {
            byte[] temp = new byte[_byteLen];
            System.arraycopy(bibyte, 0, temp, _byteLen - bibyte.length, bibyte.length);
            return temp;
        }
    }

    /**
     * SM2 私钥签名
     *
     * @param sourceStr     待签 字符串
     * @param privateKeyStr 私钥 hex串
     * @return 签名 hex串
     * @throws Exception
     */
    public static String sm2SignStr(String sourceStr, String privateKeyStr) throws Exception {
        SM2SignVO sm2SignVO = sm2Sign(sourceStr, privateKeyStr);
        return sm2SignVO.getSm2Sign();
    }

    public static SM2SignVO sm2Sign(String sourceStr, String privateKeyStr) throws Exception {
        return SM2VerifySign.sign2SM2(CryptoUtil.hex2bin(privateKeyStr), sourceStr.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * SM2 私钥签名
     *
     * @param sourceStr     待签串
     * @param privateKeyStr 私钥
     * @param userId        用户标识
     * @return
     * @throws Exception
     */
    public static String sm2SignStr(String sourceStr, String privateKeyStr, String userId) throws Exception {
        SM2SignVO sm2SignVO = sm2Sign(sourceStr, privateKeyStr, userId);
        return sm2SignVO.getSm2Sign();
    }


    public static SM2SignVO sm2Sign(String sourceStr, String privateKeyStr, String userId) throws Exception {
        return SM2VerifySign.sign2SM2(CryptoUtil.hex2bin(privateKeyStr), sourceStr.getBytes(StandardCharsets.UTF_8), userId.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * SM2 公钥验签
     *
     * @param signStr      签名
     * @param sourceStr    待验证 字符串
     * @param publicKeyStr 公钥 非压缩公钥 hex串
     * @return
     */
    public static boolean sm2Verify(String signStr, String sourceStr, String publicKeyStr) {
        publicKeyStr = sm2PublicKey130to128(publicKeyStr);
        return sm2Verify(CryptoUtil.hex2bin(signStr), sourceStr.getBytes(StandardCharsets.UTF_8), CryptoUtil.hex2bin(publicKeyStr));
    }

    /**
     * SM2 公钥验签
     *
     * @param signBytes   签名 字节数组
     * @param sourceBytes 待验证 字节数组
     * @param publicKey   公钥 非压缩公钥 字节数组
     * @return
     */
    public static boolean sm2Verify(byte[] signBytes, byte[] sourceBytes, byte[] publicKey) {
        SM2SignVO sm2SignVO = SM2VerifySign.verifySignSM2(publicKey, sourceBytes, signBytes);
        return sm2SignVO.isVerify;

    }

    public static boolean sm2Verify(byte[] signBytes, byte[] sourceBytes, byte[] publicKey, byte[] userId) {
        SM2SignVO sm2SignVO = SM2VerifySign.verifySignSM2(publicKey, sourceBytes, signBytes, userId);
        return sm2SignVO.isVerify;

    }


    public static boolean paySm2Verify(String sign, String origData, String publicKeyStr, String certId) {
        String signRHex = sign.substring(0, sign.length() / 2);
        String signSHex = sign.substring(sign.length() / 2);
        SM2SignVO sm2SignVO = SM2VerifySign.verifySignSM2NoASN1(CryptoUtil.hex2bin(publicKeyStr), origData.getBytes(StandardCharsets.UTF_8), certId.getBytes(StandardCharsets.UTF_8), new BigInteger(signRHex, 16), new BigInteger(signSHex, 16));
        return sm2SignVO.isVerify;

    }

    /*↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑SM2↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/

    /**
     * 生成SM2 公私密钥对
     * 生成公钥为 130位 带标记头非压缩公钥
     *
     * @return 公私密钥 hex 串
     */
    public static AsymmetricKey genSm2Key() {

        SM2KeyVO sm2KeyVO = SMUtil.generateKeyPair2();
        AsymmetricKey asymmetricKey = new AsymmetricKey();
        asymmetricKey.setPublicKey(CryptoUtil.bin2hex(sm2KeyVO.getPublicKey().getEncoded(false)));
        asymmetricKey.setPrivateKey(CryptoUtil.bin2hex(sm2KeyVO.getPrivateKey().toByteArray()));
        return asymmetricKey;
    }

    /**
     * 将 128 位sm2 public key 转换成130位
     *
     * @param publicKey128 128不带标记头的公钥
     * @return
     */
    public static String sm2PublicKey128to130(String publicKey128) {
        return "04" + publicKey128;
    }

    /**
     * 去除 130 sm2 公钥的标记头
     *
     * @param publicKey130
     * @return
     */
    public static String sm2PublicKey130to128(String publicKey130) {
        if (publicKey130.startsWith("04") && publicKey130.length() == 130) {
            return publicKey130.substring(2);
        }
        return publicKey130;
    }

    /**
     * SM2 公钥压缩
     *
     * @param pk64 公钥 128 去除标记头后的非压缩公钥
     * @return 压缩后的66位公钥
     */
    public byte[] sm2LPubKey2SPubKey(byte[] pk64) {
        byte[] pk33 = new byte[33];
        for (int i = 0; i < pk64.length - 1; ++i) {
            pk33[i + 1] = pk64[i];
        }
        pk33[0] = (byte) (2 + (pk64[32 * 2 - 1] & 0x01));
        return pk33;
    }

    /**
     * 生成SM4 密钥
     *
     * @return 密钥 32位hex串
     */
    public static String genSm4Key() {
        return StringUtil.getUUID();
    }

    /**
     * 生成SM4 CBC 的IV
     *
     * @return IV 32位hex串
     */
    public static String genSm4Iv() {
        return CryptoUtil.bin2hex(StringUtil.getUUID().substring(0, 16).getBytes());
    }


    /**
     * RSA 私钥转 SM2 私钥
     *
     * @param rsaPrivateKey rsa 私钥
     * @throws
     */
    public static String rsaPrivateKeyToSm2PrivateKey(String rsaPrivateKey) {
        return SMUtil.rsaPrivateKeyToSm2PrivateKey(rsaPrivateKey);
    }

    /**
     * 通过sm2 计算 sm2公钥
     *
     * @param sm2PrivateKey sm2 私钥
     * @return
     */
    public static String getSm2PublicKeyFromPrivateKey(String sm2PrivateKey) {
        return SMUtil.getSm2PublicKeyFromPrivateKey(sm2PrivateKey);
    }

    /**
     * bc加解密使用旧标c1||c2||c3，此方法在加密后调用，将结果转化为c1||c3||c2
     *
     * @param c1c2c3
     * @return
     */
    public static byte[] changeC1C2C3ToC1C3C2(byte[] c1c2c3) {
        return SMUtil.changeC1C2C3ToC1C3C2(c1c2c3);
    }


    /**
     * bc加解密使用旧标c1||c3||c2，此方法在解密前调用，将密文转化为c1||c2||c3再去解密
     *
     * @param c1c3c2
     * @return
     */
    public static byte[] changeC1C3C2ToC1C2C3(byte[] c1c3c2) {
        return SMUtil.changeC1C3C2ToC1C2C3(c1c3c2);
    }


    public static void main(String[] args) {
        String a = "{\"token\":\"3cc54ec2fe86402f9bc51d1f0f0881c6\"}{\"data\":\"AAAAAjAxAAAAAWkAAACAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAAAAgNzg2NDk1Y2FkMTAyNGZiOTk0NjJiZTIzODljYmJjMDgAAAADMDAxAAAA4EU3MjQ5QjU5MEZCODcwRDhERjBDMDdBN0IzNkM1NjdCODBEQjFGQUJBOEIxQTZBM0ZCQjc1RjQyRjgxQTU0NzI5NTlGQ0NGNDY5REMyNUNGNkU1NjhDMDMxRTA5MDJGNTdCOTA2Nzc2MTE5REE1NkI0OENGRTg0RDA4Q0QyMjlGRDU1NEZBMkQxNjM5NEU5NzdENDQ0QTM3MDNEQkE3QzdBODAyQUExOUQwQzdFMTFBQzJFQzMwN0I1NTg3QjJERTUwNTgwM0U2NUY2NDJDQTAyOEEyMjUzQTdBNURDNjZDAAAAoNe2YfcFmlDFCN+8r8repdCGb6SG3WGxgN8roFggqpshm29VmYdLAYu6KjXvCzDNoGNPKlRe4hgN2ETdL/ZPb8c5QO0n5BieMBw077fMUnxBD34kNKUmmFRjfw8Xa+Na6VGVyeeimfAXNoYuZpDV+eMGlh+D0Et3uYNWdUQuBqykMY20nS1UYkGb0SsD1zSMkzzvOWj64LIsmlzKEUIiFmUAAAAQGZ3vmQUmmC5DzVvi1LclWQAAAAF0AAAAIIM314HsfOzM0QVvgEIK63lEHeNjcNCkYHt7kIu1HcDv\"}";
        System.out.println(sm3(a));
        System.out.println(sm3(a));


        String dbPwd = "924dbb6f876b7c09bbe3952733bfa2f2149addaa138c8fd1c479a736e2958750";
        String b = sm4ECBDecrypt(dbPwd);
        System.out.println("数据库密码明文:" + b);


        //16位字符串是否是16位字节数组长度
        String strPwd = "1234567890123456";
//        String sm4Key = Util.byteToHex(strPwd.getBytes(StandardCharsets.UTF_8));
//        System.out.println(new String(Util.hexStringToBytes(sm4Key)));
        //数据库,redis 密码采用gm4加密,秘钥：30326262663532633535653434653738
        String sm4Key = "30326262663532633535653434653738";
        String localPwd = "123456";
        String m = sm4ECBEncrypt(localPwd,sm4Key);
        System.out.println("sm4加密ECB（字符串）:\n" + m);
        String m1 = sm4ECBDecrypt(m,sm4Key);
        System.out.println("sm4解密ECB（明文）:\n" + m1);
        //数据库密码解密
        String dbPwd1 = "8a665c8be8c89e6e9819553af1ce43f0";
        String b1 = sm4ECBDecrypt(dbPwd1);
        System.out.println("数据库密码明文:" + b1);
        //数据库 10.0.30.43:3306
        //密码加密
        String dbpwd2 = "Zjj11981";
        String m2 = sm4ECBEncrypt(dbpwd2,sm4Key);
        System.out.println("sm4加密ECB（字符串）:\n" + m2);

        //数据库 10.0.30.43:3306
        //密码加密
        String dbpwd3 = "1234";
        String m3 = sm4ECBEncrypt(dbpwd3,sm4Key);
        System.out.println("sm4加密ECB（字符串）:\n" + m3);

        //redis 10.0.21.100:6379
        //密码加密
        String redisPwd = "123456";
        String redisM = sm4ECBEncrypt(redisPwd,sm4Key);
        System.out.println("sm4加密ECB（字符串）:\n" + redisM);
    }

    public static void main1(String[] args) {
        String s = "e70649cd33f9f73b862e2c08636866660780eddd1d7e716296d345355075d20a5afcc3f22400012439bf2140900adbe5a2345b1855c8f9691ceaf38764a8295ca9b21bce13740150e9830993ce8c3852cb0fa2b2ab4e05d9b1aaeb73bb4c7a8fe25e0620a4ab5c65864ee420ad27b486a583954ea99fb04a83895c10a4c8ffeffa7af84fe9601d61e315cbcf0dab80814b3a42a5d678cc4dc66df0faa8db49302c852530684a084b4a20d6ce7a00b3116d39ae841c2b3993a5bfb308501bc3fdd2a2e0f254fe3abc468694cff5118bb17f516cccc7ad9e513fd2a9819db7824256c72dc2656a35a9f2ab560f827f027193a7fefd35135b3502698f865c60abaa9531a4936c5190f1552fa653cd799859b9e9b04a4e1aa6c8e0844f1fcb3d53df73d26e48fa466cfbe31e6e747482aee481f3514e5986112c0588b30f057dbda16f8ff95290d3cedf4b0076ed60bce76b428c86c9d123a5751767562306e80214f96adfc00344cca7625a904a871e79fb0e8b0ead090b7b34428319c8a03a2b38d023224a7ace0aeb7ff7a77651aab94a019d1dd7229fd30421d21394bff7cc29453fe7b617fbda04eb784592ef0fef6845b1502158c3b40e360cfe2377526dfc7bca805abffb0ecfb5a44dd7ef783b5b94b5bf32e47a1771d1ceec1146af62cdb26555c648fdc2207409c610ae308b9f65cd29308af0321fca61c166d9b7968c08dc94f08dde29c4c391ba4e0a5d9ce12d59cc70608538edf123dff2e36c05e3123ed252ca5cf00ef846d806cee4aaf26761b4cd567e5622f471ad435cc799cc62c794b41698c167109c53bb4980c9de95cc89b8e23cb5ed924e0e4e63650a2a5f2514119f58009b0b1e886ba83b760571bf3dfd73f1aa03246c711ac66a28434bd27bf68732438d40bf6389ae7c01e63d41f59b305d0d7aa48d2adb15b44dc4e6fb6396038324ea06f156bd3ccc535d8b6ce2ad413734e4173ca0f11bdf030b65188f9bf70656f27d1b3325aba97d9e177c2320e2199192efd4f9fd59a71952856a6383d9e5a20a696177666d8878a111e428d010317f443b3305fc068333e4d6405fbd6d56c35edb409ac9b794fa1db74b58c26becdd6eaa9bb95512ee1909285d86e8390162664bb8745690ddccb4e298813116a5e336eb58b775a481d4fcc86c2716d64cc6bf646ccadeebe94ea3cf6ca8132ab385b92b86d8224cb7f43a349ce581df6078626d2004336f15f53bdc0f013afe7da794c14235d07972d1fc64534d3f6be82e51c78b307d6681281a9f3d4ce3f09b9c06f227e6e2fd8548eb5bcb14fa1c0feeac64e1abd8a7fbb5b276a25a106a1f9076785022c36d36e799565aaa1ea63d5f65eb60128632cb92c4a6f8f90167409e381388bc1357e5ef1956075b014789c35a298fa45d22611b712af33fe023891c367c12bac11811b373c7533ed6a9164b8dfcb649ae57b4b0341dc78886703af77ecc7f0eb36cd7c2fa1ebe6d2c357357201cb655ebc553ffa2573b72e6e324f41f2cdfab94602512b58f7e8ee51b4ce16addb4224bc60da652a493b122fca512ae4efd27394c0fc66539b6b403d20a18dfc41d2ca919d3de272a391dc029658b2ddf4edd505ac4fae2b0f8ae9a52e3b0a10f1f1eab23a0e773bd982ecbc78f0324d2d308e4eaee5082fb16136fd101ffda46b05b816cd4f98cd360b4d13d439d9efb7e0fb9c6cb48219d6fba0a548259bc0efa3f0307035abda6729648790afd99811e9319a3dcb4524b4abb0a72c1e7356f1080fa609d31c76d45cbf4aa09c575c1d0ba31ab4d61ffaee9e56021bb497770ec4cf0ac957b5d4a03f677e98353451beb19e02120678fab364e47f6ffb01d59719171e5a18427506c598e8a4cb27e112097858f45c3613715bc76f9998d1de48ea64381e33d9b3a096a374af4bfc8f733109806c281b5";
        String sm4Key = "30326262663532633535653434653738";
        System.out.println("sm4解密ECB(字符串)：\n" + sm4ECBDecrypt(s, sm4Key));
        System.out.println("sm4解密ECB(字节)：\n" + new String(sm4ECBDecrypt(CryptoUtil.hex2bin(s), CryptoUtil.hex2bin(sm4Key), false)));
        // System.out.println(GmUtils.genSm4Key());
        // System.out.println(UUID.randomUUID().toString().replaceAll("-", ""));
    }

    public static void main2(String[] args) throws Exception {
        String sourceStr = "{\"shop\":\"ALL\",\"scr_id\":900000001,\"user_name\":\"ysftest\",\"true_name\":\"ysftest\",\"roles_id\":\"10,12,14\",\"role_name\":\"系统管理员,云平台用户,收银员\",\"mobile\":\"15171888087\",\"email\":\"1565489@qq.com\",\"shop_num\":0,\"status\":1,\"mct_no\":1,\"mct_name\":\"云闪付测试商户个人法人账户结算\",\"brand_name\":\"测试商户\",\"logo\":\"\",\"shop_no\":1,\"shop_name\":\"云闪付测试商户\",\"shop_full_name\":\"云闪付测试商户\",\"org_no\":860000000,\"agent_no\":1,\"roles\":{\"10\":\"系统管理员\",\"11\":\"云平台管理员\",\"12\":\"云平台用户\",\"13\":\"店长\",\"14\":\"收银员\"},\"auths\":{\"1\":{\"channel_name\":\"系统管理\",\"auth\":{\"1\":\"管理员列表\",\"2\":\"新增管理员\",\"3\":\"修改管理员\"}},\"20\":{\"channel_name\":\"收银台\",\"auth\":{\"112\":\"修改终端属性\",\"97\":\"收银台基础权限\",\"98\":\"普 \n" + "通收银\",\"99\":\"查帐（交易订单）\",\"100\":\"应用市场\",\"101\":\"添加应用\",\"102\":\"使用应用\",\"103\":\"配置应用\",\"105\":\"修改登录密码\",\"106\":\"修改主管密码\",\"125\":\"设置自定义支付方式\"}},\"21\":{\"channel_name\":\"商户云平台\",\"auth\":{\"113\":\"更改手机号\",\"130\":\"设置应用\",\"114\":\"应用市场\",\"115\":\"添加应用\",\"116\":\"我的应用\",\"117\":\"使用应用\",\"119\":\"数据报表\",\"107\":\"商户云平台基础权限\",\"108\":\"修改登录密码\",\"109\":\"管理员管理\",\"110\":\"门店管理\",\"127\":\"角色管理\",\"111\":\"修改门店主管密码\"}}}}";
        // SM3 摘要
        /* System.out.println("sm3：\n" + sm3(sourceStr)); */
        final byte[] SRC_DATA_16B = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8};
        // 生成SM4 密钥
        String sm4Key = "30326262663532633535653434653738";

        System.out.println("sm4Key：\n" + sm4Key);
        // System.out.println("明文：\n" + sourceStr);
        // String sm4Encrypt = sm4ECBEncrypt(sourceStr, sm4Key);
        //
        // System.out.println("sm4加密ECB(字符串)：\n" + sm4Encrypt);
        // System.out.println("sm4解密ECB(字符串)：\n" + sm4ECBDecrypt(sm4Encrypt, sm4Key));
        System.out.println("明文字节：\n" + Arrays.toString(SRC_DATA_16B));
        byte[] bytes = sm4ECBEncrypt(SRC_DATA_16B, CryptoUtil.hex2bin(sm4Key), true);
        System.out.println("sm4加密ECB(字节)：\n" + Arrays.toString(bytes));
        System.out.println("sm4解密ECB(字节)：\n" + Arrays.toString(sm4ECBDecrypt(bytes, CryptoUtil.hex2bin(sm4Key), true)));


        // 生成CBC要的IV
        String iv = genSm4Iv();
        System.out.println("sm4IV：\n" + iv);
        String sm4Encrypt1 = sm4CBCEncrypt(sourceStr, sm4Key, iv);
        System.out.println("sm4加密CBC(字符串)：\n" + sm4Encrypt1);
        System.out.println("sm4解密CBC(字符串)：\n" + sm4CBCDecrypt(sm4Encrypt1, sm4Key, iv));
        byte[] bytes1 = sm4CBCEncrypt(sourceStr.getBytes(StandardCharsets.UTF_8), CryptoUtil.hex2bin(sm4Key), CryptoUtil.hex2bin(iv), true);
        System.out.println("sm4加密CBC(字节)：\n" + Arrays.toString(bytes1));
        System.out.println("sm4解密CBC(字节)：\n" + Arrays.toString(sm4CBCDecrypt(bytes1, CryptoUtil.hex2bin(sm4Key), CryptoUtil.hex2bin(iv), true)));

        // 生成sm2 key
        AsymmetricKey sm2Key = genSm2Key();
        // 实际使用要去除04前缀
        String publicKey = GmUtils.sm2PublicKey130to128(sm2Key.getPublicKey());
        String privateKey = sm2Key.getPrivateKey();
        System.out.println("SM2 publicKey：\n" + sm2Key.getPublicKey());
        System.out.println("SM2 privateKey：\n" + sm2Key.getPrivateKey());
        String sm2str = sm2EncryptByPublicKey(sourceStr, publicKey);
        System.out.println("sm2公钥加密：\n" + sm2str);
        System.out.println("sm2私钥解密：\n" + sm2DecryptByPrivateKey(sm2str, privateKey));

        String sm2Sign = sm2SignStr(sourceStr, privateKey);
        System.out.println("sm2私钥签名：\n" + sm2Sign);
        System.out.println("sm2公钥验签：\n" + sm2Verify(sm2Sign, sourceStr, publicKey));

    }
}
